; fe3rd.asm
; FE3 RAM Disk

	.include "fe3def.inc"
	.include "vicrom.inc"
	.include "rdglobal.inc" 
	.include "rdmain.inc"
	.include "rdmem.inc"
	.include "autostart.inc"

	.export rd_open
	.export rd_close
	.export rd_save
	.export rd_load
	.export rd_chkin
	.export rd_ckout
	.export rd_clrch
	.export rd_clall
	.export nmi_handler
	.export rd_nmi 

	.export rd_main

	.export save_pg

; I/O base addresses
VIC_BASE = $9000
VIA1_BASE = $9110
VIA2_BASE = $9120

; Some VIA registers
REG_ORB = 0
REG_ORA = 1
REG_DDRB = 2
REG_DDRA = 3
REG_IFR = 13
REG_IER = 14

.macro longjmp address
		jsr prejmp
		jsr address
		jsr postjmp
		bcc @no_error
		jmp IOERROR		
@no_error:
		rts
.endmacro

.macro longjsr address
		jsr prejmp
		jsr address
		jsr postjmp
.endmacro

	.macro replace source, target, label
		lda source
		sta target
		lda source+1
		sta target+1
		lda #<label
		sta source
		lda #>label
		sta source+1
	.endmacro

	.segment "LTABLE"
	
c_open:		.res 2		; word aligned!
c_close:	.res 2
c_save:		.res 2
c_load:		.res 2
c_setin:	.res 2
c_setout:	.res 2
c_clrch:	.res 2
c_clall:	.res 2

	.segment "LDATA"
	
save_pg:	.res 1
sec_adr:	.res 1

	.segment "LCODE"

prejmp:		sei
			pha
			lda FE3_REG1
			sta save_pg
			lda #CODE_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			pla
			rts
			
postjmp:	pha
			lda save_pg
			sta FE3_REG1
			pla
			cli
			rts

rd_main:	; init RAM disk
			jsr initrd
			; set I/O vectors
			php
			pha
			sei
			replace OPEN_VECTOR,   c_open,   rd_open
			replace CLOSE_VECTOR,  c_close,  rd_close
			replace LOAD_VECTOR,   c_load,   rd_load
			replace SAVE_VECTOR,   c_save,   rd_save
			replace CHKIN_VECTOR,  c_setin,	 rd_chkin
			replace CKOUT_VECTOR,  c_setout, rd_ckout
			replace CLRCH_VECTOR,  c_clrch,	 rd_clrch
			replace CLALL_VECTOR,  c_clall,  rd_clall
			; Install custom NMI handler
			lda #<nmi_handler
			sta NMI_VECTOR
			lda #>nmi_handler
			sta NMI_VECTOR+1
			pla
			plp
			rts

initrd:		longjmp fn_init

rd_open:	lda $BA
			cmp device_no
			beq @call_fn
			jmp (c_open)
@call_fn:	ldx $B8			; LFN
			bne @lfn_ok
			jmp $F78D		; "not input file" (LFN = 0) 
@lfn_ok:	jsr $F3CF
			bne @file_ok
			jmp $F781		; "file open error"
@file_ok:	ldx $98
			cpx #10
			bcc @lfn_free
			jmp $F77E		; "too many files"
@lfn_free:	inc $98
			lda $B8			; LFN
			sta $0259, x
			lda $B9			; Sec. address
			sta $026D, x
			lda $BA			; device no.
			sta $0263, x
			ldy $B7			; length of file name
			beq call_open
@copyfn:	lda ($BB), y
			sta fname_buf, y
			dey
			bpl @copyfn
call_open:	longjmp fn_open			

rd_close:	jsr $F3D4
			beq fn_found
			clc			; file # not found
			rts
fn_found:	sta OUTBUF
			jsr $F3DF
			lda $BA
			cmp device_no
			bne call_close
			jsr $F3B3
			longjmp fn_close
call_close:	lda OUTBUF
			jmp (c_close)

	LOAD_LFN = 254
	SAVE_LFN = 255

; save memory ($C1) ... ($AE)
rd_save:	lda $BA
			cmp device_no
			beq @do_save
			jmp (c_save)
@do_save:	; open file
			lda #SAVE_LFN
			sta $B8
			lda #1			; Secondary address for save
			sta $B9
			jsr rd_open
			bcs @fail
			ldx #SAVE_LFN
			jsr rd_ckout
			bcs @fail
			; save start address
			lda $C1
			sta $AC
			jsr BSOUT
			bcs @fail
			lda $C2
			sta $AD
			jsr BSOUT
			bcs @fail
			; save data		
			ldy #0
@outloop:	jsr $FD11
			bcs @done
			lda ($AC), y
			jsr BSOUT
			jsr $FD1B
			bne @outloop
@done:		jsr CLRCH
			lda #SAVE_LFN
			jsr rd_close
			clc
			rts
@fail:		pha
			lda #SAVE_LFN
			jsr rd_close
			pla
			sec
			rts			

; load memory ($AE)
rd_load:	sta $93
			lda FE3_REG1
			sta save_pg
			lda $BA 
			cmp device_no
			beq @do_load
			lda $93
			jmp (c_load)
@do_load:	; clear status
			lda #0
			sta $90
			; open file
			lda #LOAD_LFN
			sta $B8
			lda $B9
			sta sec_adr
			lda #0			; Secondary address for load
			sta $B9
			jsr rd_open
			bcs @fail
			ldx #LOAD_LFN
			jsr rd_chkin
			bcs @fail
			; read start address
			jsr BASIN
			bcs @fail
			sta $AE
			jsr BASIN
			bcs @fail
			sta $AF
			; set start address
			ldx sec_adr
			jsr $E4C1
			; load data
			ldy #0
			lda $93			; load/verify flag
			bne @vrfylp
			
@loadlp:	lda $90
			and #$40
			bne @done
			jsr BASIN
			bcs @fail
			sta ($AE), y	; load
			inc $AE
			bne @loadlp
			inc $AF
			bne @loadlp
			beq @done

@vrfylp:	lda $90
			and #$40
			bne @done
			jsr BASIN
			bcs @fail
			cmp ($AE), y	; verify
			beq @match
			lda #$10		; ST := verify error
			jsr $FE6A
@match:		inc $AE
			bne @vrfylp
			inc $AF
			bne @vrfylp
			
@done:		jsr CLRCH
			lda #LOAD_LFN
			jsr rd_close
			jmp $F641
@fail:		pha
			lda #LOAD_LFN
			jsr rd_close
			pla
			sec
			rts

rd_chkin:	stx $95
			jsr $F3CF
			beq @found
			jmp $F784
@found:		jsr $F3DF
			lda device_no
			cmp $BA
			bne call_chkin
			sta $99
			longjmp fn_chkin
call_chkin: ldx $95
			jmp (c_setin)

rd_clrch:	longjsr fn_clrch
			jmp (c_clrch)

rd_clall:	longjsr fn_clall
			jmp (c_clall)
			
rd_ckout:	stx $95
			jsr $F3CF
			beq @found
			jmp $F784
@found:		jsr $F3DF
			lda device_no
			cmp $BA
			bne call_ckout
			sta $9A
			longjmp fn_ckout
call_ckout:	ldx $95
			jmp (c_setout)

nmi_handler:
			pha
			txa
			pha
			tya
			pha
			lda VIA1_BASE+REG_IFR
			bmi goon
done:		jmp $FF56				; RTI
goon:		and VIA1_BASE+REG_IER
			tax
			and #2
			bne rd_nmi
			jmp $FEDE				; handle RS232 irq
rd_nmi:		bit VIA1_BASE+REG_ORA	; ack NMI
			jsr $F734				; set clock & query RUN STOP
			jsr $FFE1				; check for RUN STOP
			bne done
			lda #MAIN_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			jsr $FD52				; Reset kernal vectors
			jsr restvec				; Set FE3 RD vectors 
			jmp $FED5				; handle RUN STOP/RESTORE without resetting KERNAL vectors 
			